#ifndef __SG_PCL_JSON_CONFIG_H__
#define __SG_PCL_JSON_CONFIG_H__

#include "../../3rd/rapidjson/document.h"
#include "../../3rd/rapidjson/rapidjson.h"
#include "../../utility/SGException.h"
#include "../../utility/SGLOG.h"
#include "../../utility/SGTimer.h"

#include "SGPCLBaseInfo.h"

namespace sgpcl
{

/// <summary>
/// 可视化设置参数类
/// </summary>
struct SGVisualConfig
{
  bool bPlot;                 // 是否可视化
  bool bSaveAsPLY;            // 是否保存为PLY
  std::string strPLYFileName; // 保存的PLY文件名
  bool bSaveAsPNG;            // 是否保存为PNG
  std::string strPNGFileName; // 保存的PNG文件名
  bool bSaveAsGIF;            // 是否保存为GIF
  std::string strGIFFileName; // 保存的PNG文件名
  float fPointSize;           // 点大小
  float fVecSize;             // 法向量矢量长度
  int nVecLevel;              // 法向量密度（每多少个点画一个法向量）
  float fPlaneScale;          // 拟合平面的尺寸
  float fAxisSize;            // 坐标系尺寸
  std::string strTitle;       // 可视化窗口名称
  union
  {
    struct
    {
      std::uint8_t r;
      std::uint8_t g;
      std::uint8_t b;
      std::uint8_t a;
    };
    std::uint32_t rgba;
  }; // 背景色
  union
  {
    struct
    {
      float pos_x;
      float pos_y;
      float pos_z;
    };
    float pos[3];
  }; // 视角坐标
  union
  {
    struct
    {
      float view_x;
      float view_y;
      float view_z;
    };
    float view[3];
  }; // 视角方向向量
  union
  {
    struct
    {
      float view_up_x;
      float view_up_y;
      float view_up_z;
    };
    float view_up[3];
  }; // 视角上方向向量

  SGPCL_API SGVisualConfig();
  SGPCL_API virtual ~SGVisualConfig() = default;

  /// <summary>
  /// 从Json文件解析参数
  /// </summary>
  /// <param name="cConfigFileName">文件路径</param>
  SGPCL_API void ParseJson(const rapidjson::Value& sJsonRoot);

  /// <summary>
  /// 初始化默认参数
  /// </summary>
  /// <returns></returns>1
  SGPCL_API static void SetDefaultValue(const rapidjson::Value& sJsonRoot);

  /// <summary>
  /// 返回默认参数
  /// </summary>
  /// <returns></returns>
  SGPCL_API static SGVisualConfig* GetDefaultValue();

private:
  static std::unique_ptr<SGVisualConfig> spDefaultValue;
};

struct SGPCLJsonConfig
{
  bool bPerform;             // 是否执行该操作
  bool bInPlace;             // 该操作后是否覆盖原点云
  SGVisualConfig sVisConfig; // 可视化参数

  SGPCL_API SGPCLJsonConfig();

  SGPCL_API virtual ~SGPCLJsonConfig() = default;

  // 是否执行该操作
  SGPCL_API bool IfPerform() const;

  // 该操作后是否覆盖原点云
  SGPCL_API bool IfInPlace() const;

  // 是否需要绘图窗口（可视化、png、gif都需要绘图窗口）
  SGPCL_API bool IfNeedPlotWindow() const;

  // 该操作后是否进行可视化
  SGPCL_API bool IfVis() const;

  // 该操作后是否保存为PNG
  SGPCL_API bool IfSaveAsPNG() const;

  // 该操作后是否保存为GIF
  SGPCL_API bool IfSaveAsGIF() const;

  /// <summary>
  /// 从Json文件解析参数
  /// </summary>
  /// <param name="cConfigFileName">文件路径</param>
  SGPCL_API void ParseJson(const rapidjson::Value& sJsonRoot, const std::string& strOperatorName);

  /// <summary>
  /// 从Json节点解析参数
  /// </summary>
  /// <param name="sJsonRoot"></param>
  /// <returns></returns>
  SGPCL_API virtual void ParseJson(const rapidjson::Value& sJsonRoot) = 0;

  /// <summary>
  /// 从字符串解析参数
  /// </summary>
  /// <param name="strJson"></param>
  /// <returns></returns>
  SGPCL_API void ParseJson(const std::string& strJson);
};

} // namespace sgpcl
#endif // !__SG_PCL_JSON_CONFIG_H__
